package com.base.core.aspect;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.HashMap;
import java.util.Map;


@Aspect
@Component
@Slf4j
public class RequestLogAspect {

    //定义请求所用时间
    private final ThreadLocal<Long> startTime = new ThreadLocal<>();



    // 定义切点 - 所有Controller包下的所有方法
    @Pointcut("execution(* com.base.moduleUser.controller..*.*(..))")
    public void controllerLog() {}

    @Before("controllerLog()")
    public void logBefore(JoinPoint joinPoint) {
        // 记录开始时间
        startTime.set(System.currentTimeMillis());
        HttpServletRequest request =
                ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                        .getRequest();

        // 获取请求参数
        Object[] args = joinPoint.getArgs();
        String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
        Map<String, Object> paramMap = new HashMap<>();
        for (int i = 0; i < paramNames.length; i++) {
            paramMap.put(paramNames[i], args[i]);
        }

         log.info("=== Request Start ===");
        log.info("请求URL: {}", request.getRequestURL().toString());
        log.info("请求方法: {}", request.getMethod());
        log.info("地址ip: {}", request.getRemoteAddr());
        log.info("Class Method: {}.{}",
                joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName());
        log.info("请求参数: {}", paramMap);
        log.info("会话ID: {}", request.getSession().getId());
    }

    @AfterReturning(pointcut = "controllerLog()", returning = "result")
    public void logAfter(Object result) {
        long costTime = System.currentTimeMillis() - startTime.get();
        startTime.remove(); // 清理ThreadLocal
        log.info("返回数据: {}", result);
        log.info("本此请求耗时: {} ms", costTime);
        log.info("=== Request End ===");
    }
}